package com.bookbuf.api.responses.parsers;

import com.bookbuf.api.responses.impl.BannerResponse;
import com.bookbuf.api.responses.impl.BooleanResponse;
import com.bookbuf.api.responses.impl.LongResponse;
import com.bookbuf.api.responses.impl.achievement.FetchAchievementDetailResponse;
import com.bookbuf.api.responses.impl.achievement.FetchCareerMapResponse;
import com.bookbuf.api.responses.impl.attendance.AttendanceContextResponse;
import com.bookbuf.api.responses.impl.attendance.AttendanceDayResponse;
import com.bookbuf.api.responses.impl.attendance.AttendanceMonthResponse;
import com.bookbuf.api.responses.impl.attendance.AttendanceStatusResponse;
import com.bookbuf.api.responses.impl.call.CallCancelResponse;
import com.bookbuf.api.responses.impl.call.CallResponse;
import com.bookbuf.api.responses.impl.coupon.CouponAliasListResponse;
import com.bookbuf.api.responses.impl.coupon.CouponAliasResponse;
import com.bookbuf.api.responses.impl.coupon.CouponListResponse;
import com.bookbuf.api.responses.impl.coupon.CouponNewResponse;
import com.bookbuf.api.responses.impl.coupon.CouponProductResponse;
import com.bookbuf.api.responses.impl.coupon.CouponResponse;
import com.bookbuf.api.responses.impl.coupon.CouponTypeListResponse;
import com.bookbuf.api.responses.impl.coupon.FetchCouponStatusResponse;
import com.bookbuf.api.responses.impl.coupon.VerifyCouponResponse;
import com.bookbuf.api.responses.impl.customer.BindCardListResponse;
import com.bookbuf.api.responses.impl.customer.CreateUserResponse;
import com.bookbuf.api.responses.impl.customer.CustomerLoginResponse;
import com.bookbuf.api.responses.impl.customer.DetectionListResponse;
import com.bookbuf.api.responses.impl.customer.PermissionResponse;
import com.bookbuf.api.responses.impl.customer.ProfileResponse;
import com.bookbuf.api.responses.impl.customer.UserDocumentResponse;
import com.bookbuf.api.responses.impl.examination.ExamPaperResponse;
import com.bookbuf.api.responses.impl.examination.ExamPaperWithExamResponse;
import com.bookbuf.api.responses.impl.examination.ExamResponse;
import com.bookbuf.api.responses.impl.examination.FetchDiscoverQuestionResponse;
import com.bookbuf.api.responses.impl.global.AppUpgradeResponse;
import com.bookbuf.api.responses.impl.global.RoleResponse;
import com.bookbuf.api.responses.impl.global.SplashScreenResponse;
import com.bookbuf.api.responses.impl.healthlive.CategoryListResponse;
import com.bookbuf.api.responses.impl.healthlive.FetchHealthLiveListResponse;
import com.bookbuf.api.responses.impl.healthlive.FetchRelatedHealthLiveListResponse;
import com.bookbuf.api.responses.impl.healthlive.HealthLiveResponse;
import com.bookbuf.api.responses.impl.integral.IntegralListResponse;
import com.bookbuf.api.responses.impl.measure.add.AddRecordResponse;
import com.bookbuf.api.responses.impl.measure.latest.LatestMeasureResponse;
import com.bookbuf.api.responses.impl.measure.list.ListRecordResponse;
import com.bookbuf.api.responses.impl.medical.DepartmentResponse;
import com.bookbuf.api.responses.impl.medical.DoctorResponse;
import com.bookbuf.api.responses.impl.medical.DoctorScheduleResponse;
import com.bookbuf.api.responses.impl.medical.HospitalResponse;
import com.bookbuf.api.responses.impl.medical.MedicalRegisterResponse;
import com.bookbuf.api.responses.impl.message.MessageResponse;
import com.bookbuf.api.responses.impl.monitor.MonitorCountResponse;
import com.bookbuf.api.responses.impl.order.OrderDetailResponse;
import com.bookbuf.api.responses.impl.order.OrderGenerateResponse;
import com.bookbuf.api.responses.impl.order.OrderPayResponse;
import com.bookbuf.api.responses.impl.order.OrderResponse;
import com.bookbuf.api.responses.impl.order.OrderResultResponse;
import com.bookbuf.api.responses.impl.order.PayResultResponse;
import com.bookbuf.api.responses.impl.question.QuestionResponse;
import com.bookbuf.api.responses.impl.task.TaskContextResponse;
import com.bookbuf.api.responses.impl.train.FetchLessonResponse;
import com.bookbuf.api.responses.impl.train.FetchSignUpCourseResponse;
import com.bookbuf.api.responses.impl.train.FetchTrainResponse;
import com.bookbuf.api.responses.impl.user.ClerkResponse;
import com.bookbuf.api.responses.impl.user.CredentialResponse;
import com.bookbuf.api.responses.impl.user.CustomerResponse;
import com.bookbuf.api.responses.impl.user.FetchClerkProfileResponse;
import com.bookbuf.api.responses.impl.weather.WeatherResponse;
import com.bookbuf.api.responses.parsers.impl.BannerResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.achievement.FetchAchievementDetailResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.achievement.FetchCareerMapResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.attendance.AttendanceContextResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.attendance.AttendanceDayResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.attendance.AttendanceMonthResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.attendance.AttendanceStatusResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.call.CallCancelResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.call.CallResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.coupon.CouponAliasListResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.coupon.CouponAliasResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.coupon.CouponListResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.coupon.CouponNewResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.coupon.CouponProductResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.coupon.CouponResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.coupon.CouponTypeListResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.coupon.FetchCouponStatusResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.customer.BindCardResponseListJSONImpl;
import com.bookbuf.api.responses.parsers.impl.customer.CreateUserResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.customer.CustomerLoginResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.customer.DetectionListResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.customer.PermissionResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.customer.ProfileResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.customer.UserDocumentResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.examination.ExamPaperResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.examination.ExamPaperWithExamResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.examination.ExamResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.examination.ExamTerminateBooleanResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.global.AppUpgradeResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.global.CheckUserByQueryResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.global.RoleResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.global.SplashScreenResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.healthlive.CategoryListResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.healthlive.FetchHealthLiveListResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.healthlive.FetchRelatedHealthLiveListResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.healthlive.HealthLiveResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.integral.IntegralListJSONImplResponse;
import com.bookbuf.api.responses.parsers.impl.measure.add.AddRecordResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.measure.latest.LatestMeasureResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.measure.list.ListRecordResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.medical.DepartmentResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.medical.DoctorResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.medical.DoctorScheduleResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.medical.HospitalResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.medical.MedicalRegisterResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.message.FetchNewsMessageResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.message.MessageResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.monitor.MonitorCountResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.order.OrderDetailResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.order.OrderGenerateResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.order.OrderPayResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.order.OrderResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.order.OrderResultResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.order.PayResultResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.origin.BooleanResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.origin.LongResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.question.CreateExaminationRecordResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.question.FetchDiscoverQuestionResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.question.QuestionAnswerBooleanResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.question.QuestionResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.task.TaskContextResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.train.FetchLessonResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.train.FetchSignUpCourseResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.train.FetchTrainResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.user.ClerkResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.user.CredentialResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.user.CustomerResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.user.FetchClerkProfileResponseJSONImpl;
import com.bookbuf.api.responses.parsers.impl.weather.WeatherResponseJSONImpl;
import com.ipudong.core.Result;
import com.ipudong.core.status.IStatusCode;
import com.ipudong.util.basic.ApiLog;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.List;

/**
 * author: robert.
 * date :  16/8/2.
 */
public final class InternalFactoryImpl implements InternalFactory {

    /**
     * 这里认为服务端未做处理的值是没有意义的，所以在此处加以转化确保客户端不会崩溃
     *
     * @param json 原始请求结果
     * @return JSONObject
     */
    private static JSONObject compatibleWithMAPI(JSONObject json) {

        Object model = InternalParseUtil.getObject("model", json);

        JSONObject root = new JSONObject();
        try {
            root.put("root", model);
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return root;
    }

    public static final <T> List<T> build(JSONArray array, Build<T> build) {

        List<T> list = new ArrayList<>();
        if (array != null && array.length() > 0) {
            try {
                for (int i = 0; i < array.length(); i++) {
                    JSONObject jsonObject = (JSONObject) array.get(i);
                    T t = build.createResponse(jsonObject);
                    list.add(t);
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
        return list;
    }

    private <T> Result<T> wrapper(JSONObject jsonObject, IFillResultModel<T> callback) {
        Result<T> result = new Result<>();
        result.setSuccess(InternalParseUtil.getBoolean("success", jsonObject));
        result.setMsgCode(InternalParseUtil.getInt("msgCode", jsonObject));
        if (result.isSuccess() && result.getMsgCode() == -1) {
            result.setMsgCode(IStatusCode.CODE_SUCCESS);
            result.setModel(callback.parseModel());
        } else {
            try {
                result.setModel(callback.parseModel());
            } catch (Exception e) {
                ApiLog.logger.w(e.getMessage());
                result.setModel(null);
            }
        }
        result.setMsgContent(InternalParseUtil.getRawString("msgInfo", jsonObject));
        result.setCount(InternalParseUtil.getInt("count", jsonObject));
        return result;
    }

    @Override
    public Result<AppUpgradeResponse> createAppUpgradeResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<AppUpgradeResponse>() {
            @Override
            public AppUpgradeResponse parseModel() {
                return new AppUpgradeResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<RoleResponse> createRoleResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<RoleResponse>() {
            @Override
            public RoleResponse parseModel() {
                return new RoleResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<CredentialResponse> createCredentialResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<CredentialResponse>() {
            @Override
            public CredentialResponse parseModel() {
                return new CredentialResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<ClerkResponse> createClerkResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<ClerkResponse>() {
            @Override
            public ClerkResponse parseModel() {
                return new ClerkResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<FetchClerkProfileResponse> createFetchClerkProfileResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<FetchClerkProfileResponse>() {
            @Override
            public FetchClerkProfileResponse parseModel() {
                return new FetchClerkProfileResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<CustomerResponse> createCustomerResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<CustomerResponse>() {
            @Override
            public CustomerResponse parseModel() {
                return new CustomerResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<MedicalRegisterResponse> createMedicalRegisterResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<MedicalRegisterResponse>() {
            @Override
            public MedicalRegisterResponse parseModel() {
                return new MedicalRegisterResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<List<MedicalRegisterResponse>> createMedicalRegisterResponseList(final JSONObject json) {

        return wrapper(json, new IFillResultModel<List<MedicalRegisterResponse>>() {
            @Override
            public List<MedicalRegisterResponse> parseModel() {

                Object object = InternalParseUtil.getObject("root", compatibleWithMAPI(json));
                JSONArray array = null;
                if (object instanceof JSONArray) {
                    array = (JSONArray) object;
                }
                List<MedicalRegisterResponse> list = build(array, new Build<MedicalRegisterResponse>() {
                    @Override
                    public MedicalRegisterResponse createResponse(JSONObject json) {
                        return new MedicalRegisterResponseJSONImpl(json);
                    }
                });
                return list;
            }
        });
    }

    @Override
    public Result<List<HospitalResponse>> createHospitalResponseList(final JSONObject json) {

        return wrapper(json, new IFillResultModel<List<HospitalResponse>>() {
            @Override
            public List<HospitalResponse> parseModel() {

                JSONObject object = (JSONObject) InternalParseUtil.getObject("root", compatibleWithMAPI(json));
                final JSONArray array = (JSONArray) InternalParseUtil.getObject("hospital_list", object);
                final List<HospitalResponse> list = build(array, new Build<HospitalResponse>() {
                    @Override
                    public HospitalResponse createResponse(JSONObject json) {
                        return new HospitalResponseJSONImpl(json);
                    }
                });

                return list;
            }
        });
    }

    @Override
    public Result<List<DepartmentResponse>> createDepartmentResponseList(final JSONObject json) {

        return wrapper(json, new IFillResultModel<List<DepartmentResponse>>() {
            @Override
            public List<DepartmentResponse> parseModel() {
                JSONObject object = (JSONObject) InternalParseUtil.getObject("root", compatibleWithMAPI(json));
                JSONObject schedules = (JSONObject) InternalParseUtil.getObject("Departments", object);
                JSONArray array = (JSONArray) InternalParseUtil.getObject("Department", schedules);
                final List<DepartmentResponse> list = build(array, new Build<DepartmentResponse>() {
                    @Override
                    public DepartmentResponse createResponse(JSONObject json) {
                        return new DepartmentResponseJSONImpl(json);
                    }
                });
                return list;
            }
        });
    }

    @Override
    public Result<List<DoctorResponse>> createDoctorResponseList(final JSONObject json) {

        return wrapper(json, new IFillResultModel<List<DoctorResponse>>() {
            @Override
            public List<DoctorResponse> parseModel() {
                JSONObject object = (JSONObject) InternalParseUtil.getObject("root", compatibleWithMAPI(json));
                JSONObject schedules = (JSONObject) InternalParseUtil.getObject("Schedules", object);
                JSONArray array = (JSONArray) InternalParseUtil.getObject("Schedule", schedules);
                final List<DoctorResponse> list = build(array, new Build<DoctorResponse>() {
                    @Override
                    public DoctorResponse createResponse(JSONObject json) {
                        return new DoctorResponseJSONImpl(json);
                    }
                });
                return list;
            }
        });
    }

    @Override
    public Result<ProfileResponse> createProfileResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<ProfileResponse>() {
            @Override
            public ProfileResponse parseModel() {
                return new ProfileResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }



    @Override
    public Result<List<DoctorScheduleResponse>> createDoctorScheduleResponseList(final JSONObject json) {

        return wrapper(json, new IFillResultModel<List<DoctorScheduleResponse>>() {
            @Override
            public List<DoctorScheduleResponse> parseModel() {

                JSONObject object = (JSONObject) InternalParseUtil.getObject("root", compatibleWithMAPI(json));
                JSONObject schedules = (JSONObject) InternalParseUtil.getObject("Schedules", object);
                JSONArray array = (JSONArray) InternalParseUtil.getObject("Schedule", schedules);
                final List<DoctorScheduleResponse> list = build(array, new Build<DoctorScheduleResponse>() {
                    @Override
                    public DoctorScheduleResponse createResponse(JSONObject json) {
                        return new DoctorScheduleResponseJSONImpl(json);
                    }
                });

                return list;
            }
        });
    }

    @Override
    public Result<BindCardListResponse> createBindCardListResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<BindCardListResponse>() {
            @Override
            public BindCardListResponse parseModel() {
                return new BindCardResponseListJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<BooleanResponse> createBooleanResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<BooleanResponse>() {
            @Override
            public BooleanResponse parseModel() {
                return new BooleanResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<LongResponse> createLongResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<LongResponse>() {
            @Override
            public LongResponse parseModel() {
                return new LongResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<SplashScreenResponse> createSplashScreenResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<SplashScreenResponse>() {
            @Override
            public SplashScreenResponse parseModel() {
                return new SplashScreenResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<BooleanResponse> createQuestionAnswerBooleanResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<BooleanResponse>() {
            @Override
            public BooleanResponse parseModel() {
                return new QuestionAnswerBooleanResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<BooleanResponse> createExamTerminateBooleanResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<BooleanResponse>() {
            @Override
            public BooleanResponse parseModel() {
                return new ExamTerminateBooleanResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<BooleanResponse> createCreateExaminationRecordResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<BooleanResponse>() {
            @Override
            public BooleanResponse parseModel() {
                return new CreateExaminationRecordResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<LongResponse> createCheckUserByQueryResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<LongResponse>() {
            @Override
            public LongResponse parseModel() {
                return new CheckUserByQueryResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<BannerResponse> createBannerResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<BannerResponse>() {
            @Override
            public BannerResponse parseModel() {
                return new BannerResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<LongResponse> createFetchNewsMessageResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<LongResponse>() {
            @Override
            public LongResponse parseModel() {
                return new FetchNewsMessageResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<TaskContextResponse> createTaskResponseList(final JSONObject json) {
        return wrapper(json, new IFillResultModel<TaskContextResponse>() {
            @Override
            public TaskContextResponse parseModel() {
                return new TaskContextResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<QuestionResponse> createQuestionResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<QuestionResponse>() {
            @Override
            public QuestionResponse parseModel() {
                return new QuestionResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<ExamPaperResponse> createExamPaperResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<ExamPaperResponse>() {
            @Override
            public ExamPaperResponse parseModel() {
                return new ExamPaperResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<ExamResponse> createExamResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<ExamResponse>() {
            @Override
            public ExamResponse parseModel() {
                return new ExamResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<ExamResponse> createExamHistoryResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<ExamResponse>() {
            @Override
            public ExamResponse parseModel() {
                return new ExamResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<List<ExamPaperWithExamResponse>> createExamPaperWithExamResponseList(final JSONObject json) {

        return wrapper(json, new IFillResultModel<List<ExamPaperWithExamResponse>>() {
            @Override
            public List<ExamPaperWithExamResponse> parseModel() {

                Object object = InternalParseUtil.getObject("root", compatibleWithMAPI(json));
                JSONArray array = null;
                if (object instanceof JSONArray) {
                    array = (JSONArray) object;
                }
                final List<ExamPaperWithExamResponse> list = build(array, new Build<ExamPaperWithExamResponse>() {
                    @Override
                    public ExamPaperWithExamResponse createResponse(JSONObject json) {
                        return new ExamPaperWithExamResponseJSONImpl(json);
                    }
                });

                return list;
            }
        });
    }

    @Override
    public Result<MessageResponse> createMessageResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<MessageResponse>() {
            @Override
            public MessageResponse parseModel() {
                return new MessageResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<List<MessageResponse>> createMessageListResponse(final JSONObject json) {

        final Object object = InternalParseUtil.getObject("root", compatibleWithMAPI(json));
        if (object instanceof JSONArray) {

            return wrapper(json, new IFillResultModel<List<MessageResponse>>() {
                @Override
                public List<MessageResponse> parseModel() {

                    final List<MessageResponse> list = build((JSONArray) object, new Build<MessageResponse>() {
                        @Override
                        public MessageResponse createResponse(JSONObject json) {
                            return new MessageResponseJSONImpl(json);
                        }
                    });

                    return list;
                }
            });
        } else {
            return wrapper(json, new IFillResultModel<List<MessageResponse>>() {
                @Override
                public List<MessageResponse> parseModel() {
                    return new ArrayList<>();
                }
            });
        }
    }

    @Override
    public Result<AttendanceStatusResponse> createAttendanceStatusResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<AttendanceStatusResponse>() {
            @Override
            public AttendanceStatusResponse parseModel() {
                return new AttendanceStatusResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<AttendanceMonthResponse> createAttendanceMonthResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<AttendanceMonthResponse>() {
            @Override
            public AttendanceMonthResponse parseModel() {
                return new AttendanceMonthResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<AttendanceDayResponse> createAttendanceDayResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<AttendanceDayResponse>() {
            @Override
            public AttendanceDayResponse parseModel() {
                return new AttendanceDayResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<AttendanceContextResponse> createAttendanceContextResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<AttendanceContextResponse>() {
            @Override
            public AttendanceContextResponse parseModel() {
                return new AttendanceContextResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<FetchCareerMapResponse> createCareerMapResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<FetchCareerMapResponse>() {
            @Override
            public FetchCareerMapResponse parseModel() {
                return new FetchCareerMapResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<FetchAchievementDetailResponse> createAchievementResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<FetchAchievementDetailResponse>() {
            @Override
            public FetchAchievementDetailResponse parseModel() {
                return new FetchAchievementDetailResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<FetchSignUpCourseResponse> createApplyCourseResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<FetchSignUpCourseResponse>() {
            @Override
            public FetchSignUpCourseResponse parseModel() {
                return new FetchSignUpCourseResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<FetchLessonResponse> createLessonResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<FetchLessonResponse>() {
            @Override
            public FetchLessonResponse parseModel() {
                return new FetchLessonResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<FetchTrainResponse> createFetchTrainResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<FetchTrainResponse>() {
            @Override
            public FetchTrainResponse parseModel() {
                return new FetchTrainResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<CouponResponse> createCouponResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<CouponResponse>() {
            @Override
            public CouponResponse parseModel() {
                return new CouponResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<CouponNewResponse> createCouponNewResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<CouponNewResponse>() {
            @Override
            public CouponNewResponse parseModel() {
                return new CouponNewResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<VerifyCouponResponse> createVerifyCouponResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<VerifyCouponResponse>() {
            @Override
            public VerifyCouponResponse parseModel() {
                return new BooleanResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<FetchCouponStatusResponse> createFetchCouponStatusResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<FetchCouponStatusResponse>() {
            @Override
            public FetchCouponStatusResponse parseModel() {
                return new FetchCouponStatusResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<CouponListResponse> createCouponListResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<CouponListResponse>() {
            @Override
            public CouponListResponse parseModel() {
                return new CouponListResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<CouponAliasListResponse> createCouponAliasListResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<CouponAliasListResponse>() {
            @Override
            public CouponAliasListResponse parseModel() {
                return new CouponAliasListResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<CouponAliasResponse> createCouponAliasResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<CouponAliasResponse>() {
            @Override
            public CouponAliasResponse parseModel() {
                return new CouponAliasResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<CouponProductResponse> createFetchProductResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<CouponProductResponse>() {
            @Override
            public CouponProductResponse parseModel() {
                return new CouponProductResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    private JSONObject compatibleWithHeWeather(JSONObject root) {
        JSONArray array = (JSONArray) InternalParseUtil.getObject("HeWeather5", root);
        if (array != null && array.length() == 1) {
            try {
                return (JSONObject) array.get(0);
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    @Override
    public Result<WeatherResponse> createWeatherResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<WeatherResponse>() {
            @Override
            public WeatherResponse parseModel() {
                return new WeatherResponseJSONImpl(compatibleWithHeWeather(json));
            }
        });
    }

    @Override
    public Result<FetchDiscoverQuestionResponse> createFetchDiscoverResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<FetchDiscoverQuestionResponse>() {
            @Override
            public FetchDiscoverQuestionResponse parseModel() {
                return new FetchDiscoverQuestionResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<CallCancelResponse> createCallCancelResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<CallCancelResponse>() {
            @Override
            public CallCancelResponse parseModel() {
                return new CallCancelResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<CallResponse> createCallResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<CallResponse>() {
            @Override
            public CallResponse parseModel() {
                return new CallResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<AddRecordResponse> createAddRecordResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<AddRecordResponse>() {
            @Override
            public AddRecordResponse parseModel() {
                return new AddRecordResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<LatestMeasureResponse> createLatestMeasureResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<LatestMeasureResponse>() {
            @Override
            public LatestMeasureResponse parseModel() {
                return new LatestMeasureResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<ListRecordResponse> createListRecordResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<ListRecordResponse>() {
            @Override
            public ListRecordResponse parseModel() {
                return new ListRecordResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<CustomerLoginResponse> createCustomerLoginResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<CustomerLoginResponse>() {
            @Override
            public CustomerLoginResponse parseModel() {
                return new CustomerLoginResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<FetchHealthLiveListResponse> createFetchHealthLiveListResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<FetchHealthLiveListResponse>() {
            @Override
            public FetchHealthLiveListResponse parseModel() {
                return new FetchHealthLiveListResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<HealthLiveResponse> createHealthLiveResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<HealthLiveResponse>() {
            @Override
            public HealthLiveResponse parseModel() {
                return new HealthLiveResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<UserDocumentResponse> createUserDocumentResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<UserDocumentResponse>() {
            @Override
            public UserDocumentResponse parseModel() {
                return new UserDocumentResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<DetectionListResponse> createDetectionListResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<DetectionListResponse>() {
            @Override
            public DetectionListResponse parseModel() {
                return new DetectionListResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<CategoryListResponse> createCategoryListResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<CategoryListResponse>() {
            @Override
            public CategoryListResponse parseModel() {
                return new CategoryListResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<FetchRelatedHealthLiveListResponse> createFetchRelatedHealthLiveListResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<FetchRelatedHealthLiveListResponse>() {
            @Override
            public FetchRelatedHealthLiveListResponse parseModel() {
                return new FetchRelatedHealthLiveListResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<OrderPayResponse> createOrderPayResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<OrderPayResponse>() {
            @Override
            public OrderPayResponse parseModel() {
                return new OrderPayResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<OrderDetailResponse> createOrderDetailResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<OrderDetailResponse>() {
            @Override
            public OrderDetailResponse parseModel() {
                return new OrderDetailResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<OrderGenerateResponse> createOrderGenerateResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<OrderGenerateResponse>() {
            @Override
            public OrderGenerateResponse parseModel() {
                return new OrderGenerateResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<OrderResponse> createOrderResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<OrderResponse>() {
            @Override
            public OrderResponse parseModel() {
                return new OrderResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<PayResultResponse> createPayResultResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<PayResultResponse>() {
            @Override
            public PayResultResponse parseModel() {
                return new PayResultResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<OrderResultResponse> createOrderResultResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<OrderResultResponse>() {
            @Override
            public OrderResultResponse parseModel() {
                return new OrderResultResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<IntegralListResponse> createIntergralListResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<IntegralListResponse>() {
            @Override
            public IntegralListResponse parseModel() {
                return new IntegralListJSONImplResponse(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<CouponListResponse> createRecomCouponResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<CouponListResponse>() {
            @Override
            public CouponListResponse parseModel() {
                return new CouponListResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<CouponTypeListResponse> createCouponTypeResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<CouponTypeListResponse>() {
            @Override
            public CouponTypeListResponse parseModel() {
                return new CouponTypeListResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<String> createStringResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<String>() {
            @Override
            public String parseModel() {
                return json.optString("model");
            }
        });
    }

    @Override
    public Result<CreateUserResponse> createUserResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<CreateUserResponse>() {
            @Override
            public CreateUserResponse parseModel() {
                return new CreateUserResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    @Override
    public Result<MonitorCountResponse> createMonitorResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<MonitorCountResponse>() {
            @Override
            public MonitorCountResponse parseModel() {
                return new MonitorCountResponseJSONImpl(json);
            }
        });
    }

    @Override
    public Result<PermissionResponse> createPermissionResponse(final JSONObject json) {
        return wrapper(json, new IFillResultModel<PermissionResponse>() {
            @Override
            public PermissionResponse parseModel() {
                return new PermissionResponseJSONImpl(compatibleWithMAPI(json));
            }
        });
    }

    interface IFillResultModel<T> {
        T parseModel();
    }

    public interface Build<T> {
        T createResponse(JSONObject json);
    }
}
